package com.ucode.springboot.starter.ESsearch.repository.impl;

import java.util.List;
import org.elasticsearch.action.DocWriteResponse.Result;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ucode.springboot.starter.ESsearch.annotation.metadata.ESDocumentData;
import com.ucode.springboot.starter.ESsearch.config.RestHighLevelClientHelper;
import com.ucode.springboot.starter.ESsearch.repository.BaseElasticsearchTemplate;
import com.ucode.springboot.starter.ESsearch.repository.ElasticsearchDocSourceTemplate;
import com.ucode.springboot.starter.ESsearch.repository.query.PageSortHighLight;
import com.ucode.springboot.starter.ESsearch.util.EsTools;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

@Component
public class ElasticsearchDocSourceTemplateImpl<T, ID> extends BaseElasticsearchTemplate implements ElasticsearchDocSourceTemplate<T, ID> {

    private static Log log = LogFactory.get(ElasticsearchDocSourceTemplateImpl.class);
    
    @Autowired
    @Override
    public void setRestHighLevelClientHelper(RestHighLevelClientHelper restHighLevelClientHelper) {
        super.setRestHighLevelClientHelper(restHighLevelClientHelper);
    }

    @Override
    public boolean save(T t) throws Exception {
        return save(t,null);
    }

    @Override
    public boolean save(T t, String routing) throws Exception {
        ESDocumentData metaData = EsTools.getDocEsIndexMetadata(t.getClass());
        String indexname = metaData.getIndexname();
        String idFieldName = metaData.getIdFieldName();
        String id = EsTools.getId(t, idFieldName);
        IndexRequest indexRequest = buildIndexRequest(indexname, id, t);
        if(StrUtil.isNotBlank(routing)){
            indexRequest.routing(routing);
        }
        IndexResponse indexResponse = restHighLevelClient.index(indexRequest, COMMON_OPTIONS);
        
        if (indexResponse.getResult() == Result.CREATED || indexResponse.getResult() == Result.UPDATED ) {
            return true;
        }else {
            return false;
        }
    }

    @Override
    public BulkResponse save(List<T> list) throws Exception {
        BulkResponse bulkResponse = null;
        if(CollUtil.isNotEmpty(list)){
            ESDocumentData metaData = EsTools.getDocEsIndexMetadata(list.get(0).getClass());
            String indexname = metaData.getIndexname();
            String idFieldName = metaData.getIdFieldName();
            BulkRequest bulkRequest = new BulkRequest();
            for(T obj : list){
                String id = EsTools.getId(obj, idFieldName);
                IndexRequest indexRequest = buildIndexRequest(indexname, id, obj);
                bulkRequest.add(indexRequest);
            }
            
            bulkResponse = restHighLevelClient.bulk(bulkRequest, COMMON_OPTIONS);
        }
        return bulkResponse;
    }

    @Override
    public boolean update(T t) throws Exception {
        ESDocumentData metaData = EsTools.getDocEsIndexMetadata(t.getClass());
        String indexname = metaData.getIndexname();
        String idFieldName = metaData.getIdFieldName();
        String id = EsTools.getId(t, idFieldName);
        UpdateResponse updateResponse = null; 
        if(StrUtil.isNotBlank(id)){
            UpdateRequest updateRequest = buildUpdateRequest(indexname, id, t);
            updateResponse = restHighLevelClient.update(updateRequest, COMMON_OPTIONS);
            if (updateResponse.getResult() == Result.UPDATED) {
                return true;
            } else {
                return false;
            }
        }
        return false;
    }

    @Override
    public BulkResponse update(List<T> list) throws Exception {
        BulkResponse bulkResponse = null;
        if(CollUtil.isNotEmpty(list)){
            ESDocumentData metaData = EsTools.getDocEsIndexMetadata(list.get(0).getClass());
            String indexname = metaData.getIndexname();
            String idFieldName = metaData.getIdFieldName();
            
            BulkRequest bulkRequest = new BulkRequest();
            for (T obj : list) {
                String id = EsTools.getId(obj, idFieldName);
                UpdateRequest updateRequest = buildUpdateRequest(indexname, id, obj);
                bulkRequest.add(updateRequest);
            }
            bulkResponse = restHighLevelClient.bulk(bulkRequest, COMMON_OPTIONS);
        }
        return bulkResponse;
    }

    @Override
    public BulkResponse update(QueryBuilder queryBuilder, T t, Class clazz, int limitcount, boolean asyn) throws Exception {
        BulkResponse bulkResponse = null;
        if(queryBuilder != null){
            ESDocumentData metaData = EsTools.getDocEsIndexMetadata(t.getClass());
            String indexname = metaData.getIndexname();
            String id = null;
            //这里要判断Id
            
            PageSortHighLight psh = new PageSortHighLight(1, limitcount);
            psh.setHighLight(null);
            
        }
        
        return null;
    }

    @Override
    public boolean updateCover(T t) throws Exception {
        return save(t);
    }

    @Override
    public boolean delete(T t) throws Exception {
        return delete(t,null);
    }

    @Override
    public boolean delete(T t, String routing) throws Exception {
        ESDocumentData metaData = EsTools.getDocEsIndexMetadata(t.getClass());
        String indexname = metaData.getIndexname();
        String id = EsTools.getId(t, metaData.getIdFieldName());
        DeleteRequest deleteRequest = buildDeleteRequest(indexname,id);
        if(StrUtil.isNotBlank(routing)){
            deleteRequest.routing(routing);
        }
        
        DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, COMMON_OPTIONS);
        if (deleteResponse.getResult() == Result.DELETED) {
            return true;
        } else {
            return false;
        }
        
    }

    @Override
    public BulkByScrollResponse delete(QueryBuilder queryBuilder, Class<T> clazz) throws Exception {
        ESDocumentData metaData = EsTools.getDocEsIndexMetadata(clazz);
        String indexname = metaData.getIndexname();
        DeleteByQueryRequest request = new DeleteByQueryRequest(indexname);
        request.setQuery(queryBuilder);
        BulkByScrollResponse bulkResponse = restHighLevelClient.deleteByQuery(request, RequestOptions.DEFAULT);
        return bulkResponse;
    }

    @Override
    public boolean deleteById(ID id, Class<T> clazz) throws Exception {
        ESDocumentData metaData = EsTools.getDocEsIndexMetadata(clazz);
        String indexname = metaData.getIndexname();
        DeleteRequest deleteRequest = buildDeleteRequest(indexname,id.toString());
        DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, COMMON_OPTIONS);
        if (deleteResponse.getResult() == Result.DELETED) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean deleteByIds(List<ID> ids, Class<T> clazz) throws Exception {
        BulkResponse bulkResponse = null;
        if(CollUtil.isNotEmpty(ids)){
            ESDocumentData metaData = EsTools.getDocEsIndexMetadata(clazz);
            String indexname = metaData.getIndexname();
            BulkRequest bulkRequest = new BulkRequest();
            for (ID id : ids) {
                bulkRequest.add(buildDeleteRequest(indexname,id.toString()));
            }
            
            bulkResponse = restHighLevelClient.bulk(bulkRequest, COMMON_OPTIONS);
        }
        
        return bulkResponse.hasFailures();
    }

}
